#![allow(warnings)]
use std::{rc::Rc, cell::RefCell};

use crate::classfile::ConstantPool;

use super::{ConstantInfo, ClassReader};

pub const REF_GET_FIELD: u8 = 1;
pub const REF_GET_STATIC: u8 = 2;
pub const REF_PUT_FIELD: u8 = 3;
pub const REF_PUT_STATIC: u8 = 4;
pub const REF_INVOKE_VIRTUAL: u8 = 5;
pub const REF_INVOKE_STATIC: u8 = 6;
pub const REF_INVOKE_SPECIAL: u8 = 7;
pub const REF_NEW_INVOKE_SPECIAL: u8 = 8;
pub const REF_INVOKE_INTEGERFACE: u8 = 9;


// CONSTANT_MethodHandle_info {
// u1 tag; // 值为15
// u1 reference_kind; // 取值范围[1-9]决定了方法句柄的类型
// u2 reference_index; // 对常量池的有效索引
// }
// reference_kind决定了引用是何类型，详细参考jvms8 章节4.4.8
// reference_index指向的常量为CONSTANT_Fieldref_info、CONSTANT_Methodref_info、CONSTANT_InterfaceMethodref_info中的一种。
#[derive(Clone)]
pub struct ConstantMethodHandleInfo {
    cp: Rc<RefCell<ConstantPool>>,
    pub reference_kind: u8,
    pub reference_index: usize
}

impl ConstantInfo for ConstantMethodHandleInfo {
    fn read_info(&mut self, reader: &mut ClassReader){
        self.reference_kind = reader.read_u8();
        self.reference_index =  reader.read_u16().into()
    }
}

impl ConstantMethodHandleInfo {
    pub fn new(cp: Rc<RefCell<ConstantPool>>) -> ConstantMethodHandleInfo {
        ConstantMethodHandleInfo { 
            cp,
            reference_kind: u8::default(), 
            reference_index: usize::default() 
        }
    }

    pub fn get_constant_pool(&self) -> Rc<RefCell<ConstantPool>> {
        self.cp.clone()
    }
}

// CONSTANT_MethodType_info {
// u1 tag; // 值为16
// u2 descriptor_index; // 指向有效的CONSTANT_Utf8_info，表示方法的描述符
// }
pub struct ConstantMethodTypeInfo {
    cp: Rc<RefCell<ConstantPool>>,
    descriptor_index: usize
}

impl ConstantInfo for ConstantMethodTypeInfo {
    fn read_info(&mut self, reader: &mut ClassReader){
        self.descriptor_index = reader.read_u16().into();
    }
}

impl ConstantMethodTypeInfo {
    pub fn new(cp: Rc<RefCell<ConstantPool>>) -> ConstantMethodTypeInfo {
        ConstantMethodTypeInfo { 
            cp,
            descriptor_index: usize::default() 
        }
    }

    pub fn get_constant_pool(&self) -> Rc<RefCell<ConstantPool>> {
        self.cp.clone()
    }

    pub fn get_descriptor_index(&self) -> usize {
        self.descriptor_index
    }
}

// CONSTANT_InvokeDynamic_info {
// u1 tag; // 值为18
// u2 bootstrap_method_attr_index; // 指向当前Class文件中引导方法表的bootstrap_methods[]数组的有效索引
// u2 name_and_type_index; // 指向常量池中CONSTANT_NameAndType的有效索引
// }

pub struct ConstantInvokeDynamicInfo {
    cp: Rc<RefCell<ConstantPool>>,
    bootstrap_method_attr_index: usize,
    name_and_type_index: usize
}

impl ConstantInfo for ConstantInvokeDynamicInfo {
    fn read_info(&mut self, reader: &mut ClassReader){
        self.bootstrap_method_attr_index = reader.read_u16().into();
        self.name_and_type_index = reader.read_u16().into();
    }
}

impl ConstantInvokeDynamicInfo {
    pub fn new(cp: Rc<RefCell<ConstantPool>>) -> ConstantInvokeDynamicInfo {
        ConstantInvokeDynamicInfo { 
            cp,
            bootstrap_method_attr_index: usize::default(), 
            name_and_type_index: usize::default() 
        }
    }

    pub fn get_constant_pool(&self) -> Rc<RefCell<ConstantPool>> {
        self.cp.clone()
    }

    pub fn name_and_descriptor(&self) -> (String, String) {
        self.cp.borrow().get_name_and_type(self.name_and_type_index)
    }

    pub fn bootstrap_method_attr_index(&self) -> usize {
        self.bootstrap_method_attr_index
    }
}
